package com.fjwt.gz.coupon.yspay;

import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson2.JSONObject;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.coupon.SendCouponBo;
import com.fjwt.gz.coupon.yspay.yspayutil.AESUtil;
import com.fjwt.gz.coupon.yspay.yspayutil.ByteUtil;
import com.fjwt.gz.coupon.yspay.yspayutil.YsParamUtil;
import com.fjwt.gz.coupon.yspay.yspayutil.YsUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Objects;

/**
 * 银盛发券
 */
@Slf4j
@Service
public class YspayCouponSendService {
    //TODO 注意： 上面记得封装一层，统一调用，通过不同通道调用不同的逻辑， sendCouponBo.getAuthConfig()里面要传银盛的公钥路径，公钥路径需要在上面一层进行获取
    private static final Logger ysPayLogger = LoggerFactory.getLogger("ysPay");

    public JSONObject couponSend(SendCouponBo sendCouponBo) {
        String logPrefix = "【银盛支付通道发券】";
        ysPayLogger.info("{}，发券进来的参数信息是：{}", logPrefix, JSONUtil.toJsonStr(sendCouponBo));
        if (Objects.isNull(sendCouponBo)) {
            throw new BizException("发券参数缺失！");
        }
        try {
            JSONObject bizJson = new JSONObject();
            bizJson.put("openid", sendCouponBo.getOpenId());
            bizJson.put("stockId", sendCouponBo.getStockId());

            YspayIsvParams isvParams = JSONObject.parseObject(sendCouponBo.getAuthConfig().toJSONString(), YspayIsvParams.class);
            ysPayLogger.info("{},配置参数：{}", logPrefix, JSONUtil.toJsonStr(isvParams));
            // 公共参数封装
            Map<String, String> reqMap = YsParamUtil.buildMchBasicMap(isvParams, YsConstants.SEND_COUPON_METHOD);
            ysPayLogger.info("{},公共参数封装后信息：{}", logPrefix, JSONUtil.toJsonStr(reqMap));
            String key = YsUtils.getKey(isvParams);
            ysPayLogger.info("{},key：{}", logPrefix, key);
            /** 2、生成对业务参数加密的密钥*/
            String check = YsParamUtil.docheckRSA(isvParams, key,sendCouponBo.getAuthConfig());
            ysPayLogger.info("{},check：{}", logPrefix, check);
            reqMap.put("check", check);
            byte[] bte = AESUtil.encrypt(com.alibaba.fastjson.JSONObject.toJSONBytes(bizJson, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
            String msgBizContent = Base64.encodeBase64String(bte);
            ysPayLogger.info("{},msgBizContent：{}", logPrefix, msgBizContent);
            reqMap.put("bizContent", msgBizContent);
            String sign = YsParamUtil.signMap(isvParams, reqMap,sendCouponBo.getAuthConfig());
            ysPayLogger.info("{},sign：{}", logPrefix, sign);
            reqMap.put("sign", sign);
            ysPayLogger.info("{},reqMap：{},url:{}", logPrefix, JSONUtil.toJsonStr(reqMap), YsConstants.SEND_COUPON_URL);
            Map<String, String> resMap = YsUtils.http(isvParams, reqMap, key, YsConstants.SEND_COUPON_URL,sendCouponBo.getAuthConfig());
            if (resMap == null || resMap.size() <= 0) {
                ysPayLogger.info("{} 银盛发券请求失败,返回内容为空，请求参数：reqMap={},key={}", logPrefix, JSONUtil.toJsonStr(reqMap), key);
                throw new BizException("垫资方发券失败");
            }

            String code = MapUtil.getStr(resMap, "code");
            String subCode = MapUtil.getStr(resMap, "subCode");
            if (!"00000".equals(code)) {
                ysPayLogger.info("{} 请求失败，请求参数：reqMap={},返回参数：{}", logPrefix, JSONUtil.toJsonStr(reqMap), JSONUtil.toJsonStr(resMap));
                throw new BizException("垫资方发券失败");
            }

            if (!"0000".equals(subCode)) {
                ysPayLogger.info("{} 请求失败，请求参数：reqMap={},返回参数：{}", logPrefix, JSONUtil.toJsonStr(reqMap), JSONUtil.toJsonStr(resMap));
                throw new BizException("垫资方：" + MapUtil.getStr(resMap, "subMsg"));
            }
            String businessData = resMap.get("businessData");
            JSONObject respJson = JSONObject.parseObject(businessData);
            ysPayLogger.info("{},发券成功返回信息：{}", logPrefix, JSONUtil.toJsonStr(respJson));
            return respJson;

        } catch (BizException e) {
            ysPayLogger.info("银盛发券失败");
            throw e;
        } catch (Exception e) {
            ysPayLogger.info("银盛发券失败");
            e.printStackTrace();
        }

        return null;
    }
}
